Skip to content

feat: #79 하루 마감 JSON API (daily_plan_finalize) 연결 - #80

Open
wngjs8114 wants to merge 2 commits into
devfrom
feature/#79-daily-plan-finalize-api
Open

feat: #79 하루 마감 JSON API (daily_plan_finalize) 연결#80
wngjs8114 wants to merge 2 commits into
devfrom
feature/#79-daily-plan-finalize-api

Conversation

@wngjs8114

Copy link
Copy Markdown
Collaborator

연관 이슈

closes #79

배경

end_of_day_modal.html(FE1, #74)이 하루 종료 UI는 갖췄지만, eodSubmit 버튼은 아직 setTimeout으로 가짜 진행 애니메이션만 보여줄 뿐 실제 제출 로직이 없었습니다. finalize_daily_plan() 서비스 함수(planner/services/progress_recorder.py)는 이미 구현돼 있어서, 오늘의 계획을 마감하는 JSON API를 연결했습니다.

작업 내용

  • planner:daily_plan_finalize (POST /planner/daily-plans/finalize/) 추가
  • 로그인한 사용자의 활성 시험기간에 속한 오늘 DailyPlan만 조회 (plan_id/날짜를 요청으로 받지 않음)
  • finalize_daily_plan(daily_plan, mark_unrecorded_as_not_done=True) 호출
    • 진행 기록이 없는 작업은 서버에서 항상 NOT_DONE으로 자동 기록 (클라이언트가 끌 수 있는 옵션 아님)
    • 미완료(PARTIAL/NOT_DONE) 작업이 있으면 복구안(분량유지형/핵심집중형) 생성 결과 반환
  • needs_recovery(미완료 작업 존재 여부)와 recovery_available(실제 생성된 복구안 존재 여부)를 분리해서 반환
    • 분량유지형·핵심집중형이 둘 다 생성 실패할 수 있어서 needs_recovery=true인데 recovery_group_id=null인 케이스를 프론트가 구분할 수 있어야 함

API 계약

Request

POST /planner/daily-plans/finalize/
{}

성공 응답 200

{
  "isSuccess": true,
  "code": "DAILY_PLAN_FINALIZED",
  "message": "오늘 계획을 마감했습니다.",
  "result": {
    "needs_recovery": true,
    "recovery_available": true,
    "recovery_group_id": "uuid-string",
    "auto_marked_not_done_count": 2
  }
}

실패 응답

  • 404 DAILY_PLAN_NOT_FOUND — 활성 시험기간 또는 오늘 계획 없음
  • 409 DAILY_PLAN_ALREADY_FINALIZED — 이미 마감된 계획

이번 PR 범위 밖

  • recovery_compare 복구안 비교 View/URL, 그리고 그에 따른 redirect_url 응답 필드 → 별도 이슈
  • FE1의 eodSubmit 클릭 핸들러 fetch 연결 → 이 API 계약 전달 후 FE1 작업

테스트

planner/tests.pyDailyPlanFinalizeViewTests 10개 케이스 추가:

  • 활성 시험기간 없음 → 404
  • 오늘 계획 없음 → 404
  • 다른 사용자의 오늘 계획만 존재 → 404
  • 전부 완료 후 마감 → needs_recovery=false
  • 일부완료/못함 작업 존재 → needs_recovery=true
  • 미입력 작업 자동 NOT_DONE 기록 → auto_marked_not_done_count 확인
  • 복구안 하나 이상 생성 → recovery_available=true, recovery_group_id 반환
  • 복구안 두 종류 모두 생성 실패 → recovery_available=false, recovery_group_id=null
  • 이미 마감된 계획 재마감 → 409
  • GET 요청 차단 → 405

python manage.py test planner

→ 138개 전체 통과 (기존 테스트 회귀 없음)

리뷰 포인트

  • needs_recovery / recovery_available 분리가 자연스러운지
  • mark_unrecorded_as_not_done=True 서버 고정 방식에 이견 없는지

@6ye0m

6ye0m commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

138개 테스트 전부 통과 확인했고(python manage.py test planner), recovery_group_id가 maintain_volume/core_focus 양쪽에 동일하게 부여되는 것도 generate_recovery_options() 코드로 직접 확인했습니다 — or 체이닝 방식이 정확합니다.

다만 _get_today_daily_plan()의 조회 순서에 실질적인 문제가 있어 보입니다.

python
def _get_today_daily_plan(user):
exam_period = (
ExamPeriod.objects.filter(user=user, status=ExamPeriodStatus.ACTIVE)
.order_by('-created_at').first()
)
if exam_period is None:
return None
return DailyPlan.objects.filter(
exam_period=exam_period, date=timezone.localdate()
).first()

시험기간을 먼저 "가장 최근 생성된 ACTIVE 것 하나"로 고정한 뒤, 그 안에서만 오늘 날짜 계획을 찾습니다.

프로젝트 전체에 ExamPeriod를 COMPLETED로 전환하는 코드가 없어서(grep -rn "status = ExamPeriodStatus.COMPLETED" 결과 없음), 사용자가 시험기간을 여러 개 만들면 전부 계속 ACTIVE로 남습니다. 이 상태에서 더 오래된 시험기간 쪽에 오늘 날짜 계획이 있어도, 최근 시험기간 안에 오늘 계획이 없으면 바로 None을 반환해 404가 뜹니다. 실제로는 마감할 계획이 분명히 있는데도요.

대시보드 쪽에서 비슷한 패턴을 이미 한 번 지적드린 적 있는데(#61), 그때는 "화면에 뭘 보여줄지"의 문제였다면 이번엔 마감이라는 되돌릴 수 없는 액션 자체를 시작하지 못하게 막는 문제라 더 실질적입니다.

제안: 시험기간을 먼저 고르지 말고 오늘 날짜인 DailyPlan을 기준으로 바로 조회하면 이 문제 자체가 없어질 것 같습니다.

python
def _get_today_daily_plan(user):
return DailyPlan.objects.filter(
exam_period__user=user,
exam_period__status=ExamPeriodStatus.ACTIVE,
date=timezone.localdate(),
).order_by('-exam_period__created_at').first()

관련해서 아래 테스트도 추가되면 좋겠습니다.

사용자가 ACTIVE 시험기간을 2개 이상 갖고 있고, 더 오래된 시험기간에만 오늘 날짜 DailyPlan이 있는 경우에도 정상적으로 마감되는지

이 부분 반영되면 나머지는 로직(트랜잭션, recovery_group_id, 에러 응답 매핑)까지 다 확인했고 문제없어 보입니다.

참고로 별개 사항인데, 직전에 리뷰했던 PR #78(progress_record)은 isSuccess 구조를 폐기하고 flat 구조로 가기로 했는데 이 PR은 isSuccess로 감싸는 구조를 씁니다. 두 PR을 같이 정리하실 때 API 응답 구조도 하나로 통일하는 걸 검토해주시면 좋겠습니다.

@wngjs8114

Copy link
Copy Markdown
Collaborator Author

리뷰 감사합니다. 요청해주신 사항 반영했습니다.

  • 최신 dev 병합 후 planner/views.py, planner/tests.py 충돌 해결
  • #78의 progress_record 구현 및 테스트 유지
  • ACTIVE 시험기간을 먼저 하나 선택하지 않고, 로그인 사용자의 ACTIVE 시험기간 중 오늘 날짜 DailyPlan을 직접 조회하도록 수정
  • 최근 ACTIVE 시험기간에는 오늘 계획이 없고, 이전 ACTIVE 시험기간에만 오늘 계획이 있는 경우의 테스트 추가
  • progress_record와 동일하게 하루 마감 API 응답을 flat JSON 구조로 통일

검증 결과:

python manage.py test planner.tests.ProgressRecordViewTests -v 2
# 12개 통과

python manage.py test planner.tests.DailyPlanFinalizeViewTests -v 2
# 11개 통과

python manage.py test planner
# 151개 통과

python manage.py check
# 이상 없음

python manage.py makemigrations --check
# No changes detected

재확인 부탁드립니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[planner] 하루 마감 API 연결 (daily_plan_finalize)

2 participants